SORACOM Beamでコマンドの実行結果を雑だけどセキュアに送信する #soracom
[2015/10/06 16:00更新]
BeamのTCP→HTTP/Sに仕様変更があり、転送されるHTTPリクエストが変わったため実行結果を訂正しました。
ども、大瀧です。
皆さん、SORACOM触ってますか?Air SIMに目が行きがちですが、IoTプラットフォームとしての利用であればプロキシサービスのBeamも検討するべき要チェックサービスですよ!
さて、IoTデバイスからクラウドへのデータ送信を考えるとき、必ず検討するのがフォーマットとプロトコルでしょう。互換性の高さからHTTPにするか、IoT向けということでMQTTにするか要件によって目移りするところだと思います。ただ、プロトコルによっては専用のクライアントライブラリが必要だったり、フォーマットの整形にあまりコンピュータリソースが割けない場合もあるのではないでしょうか。
そこで今回は、nc
ユーティリティを用いてコマンドの実行結果(標準出力)をBeam経由で"雑だけどセキュア"に送信する構成をご紹介します。
構成の概要
図で示すと以下の通りです。Beamには、TCPで送信されるテキストデータをHTTPないしHTTPSに変換しバックエンドのWebサーバーに転送する機能があるのでこれを利用します。今回はデータ送信先のクラウドとしてAWS環境を用いて、Beam-AWS(ELB)間はTLS暗号化を施します。
AWSの構成
BeamからのHTTPリクエストは特別なものではないため、任意のHTTP/HTTPSサーバーで受信できます。今回はELB+EC2で試してみました。Beamは自己署名証明書など不正なTLS通信を遮断するため、ELBではSSLターミネーションとともに有効な証明書と対応するDNS構成を準備しておきます。
EC2インスタンスでは、ApacheやNginxなど一般的なWebサーバーやアプリケーションサーバーを用いるところですが、今回はBeamが送信するHTTPリクエストをダンプするためにこちらの記事を参考にnc -l
を実行してみます。
[ec2-user@ec2 ~] $ while true; do ( echo "HTTP/1.0 200 Ok"; echo; echo "Hello World" ) | sudo nc -l 80; done
Beamの構成
続いてBeamの構成です。Beamの中継設定はSIMグループに設定するため、グループが未作成の場合は任意のグループ名で作成しておきます。
グループの設定画面を開き、[+] - [TCP → HTTP/HTTPSエントリポイント]を選択します。
任意の設定名を入力し、[プロトコル]を「HTTPS」、[ホスト名]にELB Endpointに設定したDNS名、[ポート番号]は空のまま、[パス]に「/」をそれぞれ入力します。Beam側のエントリポイントはこのあとnc
実行時に指定するので控えておきましょう。
[パラメータ操作]の部分は、今回の例では特に利用しませんが動作確認のためにそれぞれ有効化してみました。
これでOKです。
動作確認
それでは、SORACOM Air SIMを搭載したデバイスからデータを送信してみます。任意のコマンドをnc
にパイプラインで繋ぎ、Beamのエントリポイントにデータを送信します。
デバイスのターミナル
vagrant@debian-wheezy:~$ cat /proc/cpuinfo | nc beam.soracom.io 23080 ^C vagrant@debian-wheezy:~$
nc -l
を実行しているEC2のターミナル
POST / HTTP/1.1 host: XXXX.XXXX.XXXX accept: application/json content-type: application/json User_Agent: SORACOM Beam X_SORACOM_IMSI: XXXXXXXXXXXXXXX X_SORACOM_SIGNATURE: 906ac66b2440284100d9cbfa325ca9c75f0a32065218656125399f9556c07b7c X_SORACOM_SIGNATURE_VERSION: 20150901 X_SORACOM_TIMESTAMP: 1444114620657 X-Forwarded-For: XX.XX.XX.XX X-Forwarded-Port: 443 X-Forwarded-Proto: https Content-Length: 898 Connection: keep-alive {"payload":"cHJvY2Vzc29yCTogMAp2ZW5kb3JfaWQJOiBHZW51aW5lSW50ZWwKY3B1IGZhbWlseQk6IDYKbW9kZWwJCTogNjEKbW9kZWwgbmFtZQk6IEludGVsKFIpIENvcmUoVE0pIE0tNVk3MSBDUFUgQCAxLjIwR0h6CnN0ZXBwaW5nCTogNAptaWNyb2NvZGUJOiAweDE5CmNwdSBNSHoJCTogMTI5OS45NTcKY2FjaGUgc2l6ZQk6IDQwOTYgS0IKZnB1CQk6IHllcwpmcHVfZXhjZXB0aW9uCTogeWVzCmNwdWlkIGxldmVsCTogMjAKd3AJCTogeWVzCmZsYWdzCQk6IGZwdSB2bWUgZGUgcHNlIHRzYyBtc3IgcGFlIG1jZSBjeDggYXBpYyBzZXAgbXRyciBwZ2UgbWNhIGNtb3YgcGF0IHBzZTM2IGNsZmx1c2ggbW14IGZ4c3Igc3NlIHNzZTIgc3lzY2FsbCBueCByZHRzY3AgbG0gY29uc3RhbnRfdHNjIHVwIHJlcF9nb29kIG5vcGwgeHRvcG9sb2d5IG5vbnN0b3BfdHNjIHBuaSBwY2xtdWxxZHEgbW9uaXRvciBzc3NlMyBjeDE2IHNzZTRfMSBzc2U0XzIgbW92YmUgcG9wY250IGFlcyB4c2F2ZSBhdnggcmRyYW5kIGxhaGZfbG0gYWJtIDNkbm93cHJlZmV0Y2gKYm9nb21pcHMJOiAyNTk5LjkxCmNsZmx1c2ggc2l6ZQk6IDY0CmNhY2hlX2FsaWdubWVudAk6IDY0CmFkZHJlc3Mgc2l6ZXMJOiAzOSBiaXRzIHBoeXNpY2FsLCA0OCBiaXRzIHZpcnR1YWwKcG93ZXIgbWFuYWdlbWVudDoKCg=="} ^Z [1]+ 停止 ( echo "HTTP/1.0 200 Ok"; echo; echo "Hello World" ) | sudo nc -l 80 [ec2-user@ec2 ~] $
来ました!Beamからのリクエストが以下になっていることがわかりますね。
- HTTPメソッド : POST
- Content-Type : application/json
- IMSI :
X_SORACOM_IMSI
ヘッダ - 署名 :
X_SORACOM_SIGNATURE
ヘッダ - タイムスタンプ :
X_SORACOM_TIMESTAMP
ヘッダ - 送信データ : JSONの
payload
キーの値としてBASE64エンコードされた文字列
サーバーサイドのロジックで、問題無くパースできそうな感じですね。あとは煮るなり焼くなり活用できると思います。IMSIはSIM固有のIDですので、以前のエントリーでご紹介したデバイス認証に利用しても良いでしょう。念のため、payloadの文字列をbase64
コマンドでデコードしてみます。
$ echo 'cHJvY2Vzc29yCTogMAp2ZW5kb3JfaWQJOiBHZW51aW5lSW50ZWwKY3B1IGZhbWlseQk6IDYKbW9kZWwJCTogNjEKbW9kZWwgbmFtZQk6IEludGVsKFIpIENvcmUoVE0pIE0tNVk3MSBDUFUgQCAxLjIwR0h6CnN0ZXBwaW5nCTogNAptaWNyb2NvZGUJOiAweDE5CmNwdSBNSHoJCTogMTI5OS45NTcKY2FjaGUgc2l6ZQk6IDQwOTYgS0IKZnB1CQk6IHllcwpmcHVfZXhjZXB0aW9uCTogeWVzCmNwdWlkIGxldmVsCTogMjAKd3AJCTogeWVzCmZsYWdzCQk6IGZwdSB2bWUgZGUgcHNlIHRzYyBtc3IgcGFlIG1jZSBjeDggYXBpYyBzZXAgbXRyciBwZ2UgbWNhIGNtb3YgcGF0IHBzZTM2IGNsZmx1c2ggbW14IGZ4c3Igc3NlIHNzZTIgc3lzY2FsbCBueCByZHRzY3AgbG0gY29uc3RhbnRfdHNjIHVwIHJlcF9nb29kIG5vcGwgeHRvcG9sb2d5IG5vbnN0b3BfdHNjIHBuaSBwY2xtdWxxZHEgbW9uaXRvciBzc3NlMyBjeDE2IHNzZTRfMSBzc2U0XzIgbW92YmUgcG9wY250IGFlcyB4c2F2ZSBhdnggcmRyYW5kIGxhaGZfbG0gYWJtIDNkbm93cHJlZmV0Y2gKYm9nb21pcHMJOiAyNTk5LjkxCmNsZmx1c2ggc2l6ZQk6IDY0CmNhY2hlX2FsaWdubWVudAk6IDY0CmFkZHJlc3Mgc2l6ZXMJOiAzOSBiaXRzIHBoeXNpY2FsLCA0OCBiaXRzIHZpcnR1YWwKcG93ZXIgbWFuYWdlbWVudDoKCg==' \ | base64 -D processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 61 model name : Intel(R) Core(TM) M-5Y71 CPU @ 1.20GHz stepping : 4 microcode : 0x19 cpu MHz : 1299.957 cache size : 4096 KB fpu : yes fpu_exception : yes cpuid level : 20 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc up rep_good nopl xtopology nonstop_tsc pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx rdrand lahf_lm abm 3dnowprefetch bogomips : 2599.91 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: $
いい感じですね。
また、以下のように標準出力が複数回出力される場合Beamはその出力ごとにHTTPリクエストを分けてバックエンドに転送してくれるので、tail -f
/ tailf
のようなコマンドの連続実行にもうまく対応してくれるようです。
vagrant@debian-wheezy:~$ while true;do echo a;sleep 5; done | nc beam.soracom.io 23080 ^C vagrant@debian-wheezy:~$
あと恐らくマルチバイトの扱いは不得意だと思うので、デバイス側のロケール設定などに注意しましょう。
まとめ
nc
ユーティリティとBeamのTCP→HTTPS変換を利用したコマンド実行結果のデータ送信手法をご紹介しました。クラウドに手軽にデータを送る方法としていろいろ応用してみてください!